package com.scalar.chiptrack.externalusers.actions;

import com.scalar.chiptrack.ChipTrackAction;
import com.scalar.chiptrack.sales.dao.CustomerDAO;
import com.scalar.chiptrack.sales.dao.NewCustomerDAO;
import com.scalar.chiptrack.users.User;
import com.scalar.chiptrack.users.FunctionAccess;
import com.scalar.chiptrack.users.dao.UserDAO;
import com.scalar.chiptrack.utils.StringUtils;
import com.scalar.chiptrack.utils.MessageDigestUtils;
import com.scalar.chiptrack.commons.SessionKeys;
import com.scalar.chiptrack.commons.Constants;
import com.scalar.chiptrack.externalusers.forms.ExternalUserSetupForm;
import com.scalar.chiptrack.externalusers.dao.ExternalUserSetupDAO;
import com.scalar.chiptrack.db.DBTransaction;
import com.scalar.chiptrack.db.DBXException;
import com.scalar.ScalarException;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionForm;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.*;

/**
 * Created by IntelliJ IDEA.
 * User: Krishna Prasad
 * Date: Jun 29, 2004
 * Time: 4:07:23 PM
 */
public class ExternalUserSetupAction extends ChipTrackAction
{

    private static final String ACTION_NAME = "/externalUserSetup.do";
    public ActionForward execute( ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response ) throws Exception
    {

        HttpSession session = request.getSession();
        HashMap info = new HashMap();
        HashMap errors = new HashMap();
        boolean isUserExits = false;
        boolean success = false;
        DBTransaction dbTransaction = null;

        ExternalUserSetupForm externalUserSetupForm = ( ExternalUserSetupForm ) form;
        User externalUser = externalUserSetupForm.getExternalUser();
        String action = request.getParameter( "action" );

        //Get the session, to retrieve the values
        User user = ( User ) session.getAttribute( SessionKeys.USER_KEY );

        if ( user == null )
        {
            if ( "modify".equalsIgnoreCase( action ) || "update".equalsIgnoreCase( action ) )
            {
                session.setAttribute( SessionKeys.SOURCE_PAGE_KEY, ACTION_NAME + "?action=search" );
            }
            else
            {
                session.setAttribute( SessionKeys.SOURCE_PAGE_KEY, ACTION_NAME + "?" + request.getQueryString() );
            }
            return ( mapping.findForward( "login" ) );
        }

        if("sameAsUser".equalsIgnoreCase( action ))
        {
            String sameExternalUserId = request.getParameter( "sameAsUserId" );
            User tempExternalUser = externalUserSetupForm.getExternalUser();

            tempExternalUser.setPassword(null);
            //loading the function access list pertaining to the user
            ArrayList totalFunctionAccessList = ExternalUserSetupDAO.loadAllExternalFunctionalities( null );
            ArrayList userFunctionAccessList = UserDAO.loadFunctionAccessListByUserId (sameExternalUserId);//ExternalUserSetupDAO.loadAllExternalUserFunctionAccess( null, externalUserId );
            setSelectedFunctionAccess( totalFunctionAccessList, userFunctionAccessList );
            tempExternalUser.setFunctionAccessList( totalFunctionAccessList );
            tempExternalUser.setSameAsUserId(sameExternalUserId);

            externalUserSetupForm.setExternalUser( tempExternalUser );
            externalUserSetupForm.setUserAction( action );
            externalUserSetupForm.setReEnterPassword( "" );

            request.setAttribute ( "vendorList", ExternalUserSetupDAO.getAllVendorNames() );
            request.setAttribute ("customerList", CustomerDAO.getAllCustomerNamesNoStringsAttached());
            request.setAttribute ("salesPersonList", NewCustomerDAO.getSalesPersonList(null));
            request.setAttribute( "usersList", ExternalUserSetupDAO.loadAllExternalUsers(false) );

            return ( mapping.findForward( "success" ) );

        }
        if ( "view".equalsIgnoreCase( action ) || "modify".equalsIgnoreCase( action ) )
        {
            String externalUserId = request.getParameter( "extUserId" );
            User tempExternalUser = UserDAO.loadUser (externalUserId, null /*password*/, true /*load even if its expired or disabled*/);//ExternalUserSetupDAO.getExternalUser( null, externalUserId );
            if ( tempExternalUser == null )
            {
                throw new ScalarException( "The details pertaining to the given user could not be found." );
            }
            tempExternalUser.setPassword(null);
            //loading the function access list pertaining to the user
            ArrayList totalFunctionAccessList = ExternalUserSetupDAO.loadAllExternalFunctionalities( null );
            ArrayList userFunctionAccessList = UserDAO.loadFunctionAccessListByUserId (externalUserId);//ExternalUserSetupDAO.loadAllExternalUserFunctionAccess( null, externalUserId );
            setSelectedFunctionAccess( totalFunctionAccessList, userFunctionAccessList );
            tempExternalUser.setFunctionAccessList( totalFunctionAccessList );

            externalUserSetupForm.setExternalUser( tempExternalUser );
            externalUserSetupForm.setUserAction( action );
            externalUserSetupForm.setReEnterPassword( "" );

            request.setAttribute ( "vendorList", ExternalUserSetupDAO.getAllVendorNames() );
            request.setAttribute ("customerList", CustomerDAO.getAllCustomerNamesNoStringsAttached());
            request.setAttribute ("salesPersonList", NewCustomerDAO.getSalesPersonList(null));
            request.setAttribute( "usersList", ExternalUserSetupDAO.loadAllExternalUsers(false) );

            return ( mapping.findForward( "success" ) );
        }
        else if ( "save".equalsIgnoreCase( action ) || "update".equalsIgnoreCase( action ) )
        {
            request.setAttribute ( "vendorList", ExternalUserSetupDAO.getAllVendorNames() );
            request.setAttribute ("customerList", CustomerDAO.getAllCustomerNamesNoStringsAttached());
            request.setAttribute ("salesPersonList", NewCustomerDAO.getSalesPersonList(null));
            request.setAttribute( "usersList", ExternalUserSetupDAO.loadAllExternalUsers(false) );

            HashMap formErrors = validateForm ( externalUserSetupForm, action );
            if ( ( formErrors != null ) && ( formErrors.isEmpty() == false ) )
            {
                request.setAttribute( SessionKeys.ERROR_MESSAGES, formErrors );
                return ( mapping.findForward( "failure" ) );
            }

            // Encrypt password before stroing it -- one way encryption
            String encryptedPassword = null;
            if ( ( externalUser.getPassword() != null ) && ( externalUser.getPassword().trim().length() != 0 ) )
            {
                encryptedPassword = StringUtils.concatBytes( MessageDigestUtils.getMAC( externalUser.getPassword() ), "," );
                externalUser.setPassword( encryptedPassword );
            }


            dbTransaction = DBTransaction.getInstance();
            if ( dbTransaction != null )
            {
                dbTransaction.begin();
            }
            try
            {
                if ( "update".equalsIgnoreCase( action ) )
                {
                    //updating the external user details
                    UserDAO.updateUserSettings (dbTransaction, externalUser.getUserId(), encryptedPassword, externalUser.getFirstName(), externalUser.getLastName(),
                                        externalUser.getPhoneNumber(), externalUser.getFaxNumber(), externalUser.getUserGroupId(),
                                        externalUser.getLevelId(), /*externalUser.getRegionId()*/ 1, externalUser.getEmail(), externalUser.getExpiresOn(),
                                        externalUser.getReceiveNotifications(), false, false, false, false, externalUser.isQuoteAckMail(), false, externalUser.getUserType() );
                    //ExternalUserSetupDAO.insertExternalUser( dbTransaction, externalUser, false );
                    //ExternalUserSetupDAO.saveExternalUserFunctionAccess( dbTransaction, externalUser.getFunctionAccessList() );
                    ArrayList functionAccessList = externalUser.getFunctionAccessList();
                    int listSize = functionAccessList.size();
                    FunctionAccess functionAccess = null;
                    for ( int i=0; i < listSize ; i++ )
                    {
                        functionAccess = ( FunctionAccess )functionAccessList.get(i);
                        functionAccess.setUserlId( externalUser.getUserId() );
                    }
                    UserDAO.insertFunctionAccessList (dbTransaction, true, externalUser.getUserId(), functionAccessList.iterator() );
                    UserDAO.saveUserMapValues ( dbTransaction, externalUser.getUserId(), externalUser.getCustomerId(), externalUser.getVendorId(), externalUser.getSalesPersonId() );
                    info.put( "Setup information for " + externalUser.getUserId() + " has been updated successfully", null );
                    request.setAttribute( SessionKeys.INFO_MESSAGES, info );
                    clearForm( externalUserSetupForm );
                    success = true;
                }
                else if ( "save".equalsIgnoreCase( action ) )
                {
                    //isUserExits = ExternalUserSetupDAO.isExternalUserIdExist( dbTransaction, externalUser.getUserId() );
                    isUserExits = UserDAO.doesUserIdExist(dbTransaction,""+externalUser.getUserId());
                    if ( isUserExits == false )
                    {
                        //saving the external user details
                        //ExternalUserSetupDAO.insertExternalUser( dbTransaction, externalUser, true );
                        int addressId = UserDAO.insertAddress (dbTransaction, ""/*address1*/, ""/*address2*/, ""/*city*/, ""/*state*/, ""/*zipcode*/, "" /*country*/);
                        int userGroupId;
                        if ( ( externalUser.getUserType() == Constants.USER_TYPE_CUSTOMER ) || ( externalUser.getUserType() == Constants.USER_TYPE_SALES_PERSON ))
                        {
                            userGroupId = UserDAO.getUserGroupId( dbTransaction, Constants.USER_GROUP_SALES );
                        }
                        else
                        {
                            userGroupId = UserDAO.getUserGroupId( dbTransaction, Constants.USER_GROUP_OPERATIONS );
                        }
                        UserDAO.insertUser ( dbTransaction, externalUser.getUserId(), encryptedPassword, externalUser.getFirstName(), externalUser.getLastName(),
                                    userGroupId,
                                    externalUser.getLevelId(), addressId, /*externalUser.getRegionId()*/ 1, externalUser.getEmail(), externalUser.getPhoneNumber(), externalUser.getFaxNumber(),
                                    externalUser.getExpiresOn(), externalUser.getReceiveNotifications(),
                                      false, false, false, false, externalUser.isQuoteAckMail(), false, externalUser.getUserType() );

                        //setting the userID to the function access list
                        ArrayList functionAccessList = externalUser.getFunctionAccessList();
                        int listSize = functionAccessList.size();
                        FunctionAccess functionAccess = null;
                        for ( int i=0; i < listSize ; i++ )
                        {
                            functionAccess = ( FunctionAccess )functionAccessList.get(i);
                            functionAccess.setUserlId( externalUser.getUserId() );
                        }
                        /*ExternalUserSetupDAO.saveExternalUserFunctionAccess( dbTransaction, externalUser.getFunctionAccessList() );*/
                        UserDAO.insertFunctionAccessList (dbTransaction, false, externalUser.getUserId(), functionAccessList.iterator());
                        UserDAO.saveUserMapValues ( dbTransaction, externalUser.getUserId(), externalUser.getCustomerId(), externalUser.getVendorId(), externalUser.getSalesPersonId() );
                        info.put( "Setup information for " + externalUser.getUserId() + " has been saved successfully", null );
                        request.setAttribute( SessionKeys.INFO_MESSAGES, info );
                        success = true;

                        clearForm( externalUserSetupForm );

                    }
                    else
                    {
                        //show the message to the user that the user is already existing
                        errors.put( externalUser.getUserId() + " External User Id Already Exists", null );
                        request.setAttribute( SessionKeys.ERROR_MESSAGES, errors );
                        externalUserSetupForm.setPassword( null );
                        externalUserSetupForm.setReEnterPassword( null );
                        return mapping.findForward( "success" );
                    }
                }
            }
            catch ( ScalarException e )
            {
                errors.put( "External User Could Not Save into Data Base", null );
                request.setAttribute( SessionKeys.ERROR_MESSAGES, errors );

                System.out.println( "Exception while storing External User.. \n" + e.getRootCause().getMessage() + "\nRolling back" );
                e.printStackTrace();
            }
            finally
            {
                // Rollback or Commit the Transaction
                try
                {
                    if ( success == true )
                    {
                        dbTransaction.commit();
                    }
                    else
                    {
                        dbTransaction.rollback();
                    }
                }
                catch ( DBXException e )
                {
                    e.printStackTrace();
                }
            }
            return mapping.findForward( "backtosearch" );
        }
           else if ("delete".equalsIgnoreCase(action) ) {
                String userToDelete = request.getParameter("username");
                if ((userToDelete != null) && (userToDelete.trim().length() != 0)) {
                    try {
                        UserDAO.deleteUser (userToDelete);
                        info.put (userToDelete + " has been disabled", null);
                    }
                    catch (ScalarException se) {
                        // problem with database
                        se.printStackTrace ();
                        errors.put ("Internal Server Error", "Could not delete \"" + userToDelete + "\"");
                    }
                }
                return mapping.findForward( "backtosearch" );
            }


            // ACTIVATE THE USER
            else if ("activate".equalsIgnoreCase(action))
            {
                String userToActivate = request.getParameter("username");
                if ((userToActivate != null) && (userToActivate.trim().length() != 0))
                {
                    try
                    {
                        UserDAO.activateUser (userToActivate);
                        info.put (userToActivate + " has been activated", null);
                    }
                    catch (ScalarException se)
                    {
                        se.printStackTrace ();
                        errors.put ("Internal Server Error", "Could not activate \"" + userToActivate + "\"");
                    }
                }
                return mapping.findForward( "backtosearch" );
            }
        else if ( "search".equalsIgnoreCase( action ) )
        {
            try
            {
                ArrayList extUserList = new ArrayList();
                extUserList = ExternalUserSetupDAO.loadAllExternalUsers( null, externalUserSetupForm );
                request.setAttribute( "AllExternalUserList", extUserList );

            }
            catch ( ScalarException e )
            {
                errors.put( "Could not Load All Users", null );
                request.setAttribute( SessionKeys.ERROR_MESSAGES, errors );
                System.out.println( "Exception while loading External Users.. \n" + e.getRootCause().getMessage() );
                e.printStackTrace();
            }

            request.setAttribute( "vendorList", ExternalUserSetupDAO.getAllVendorNames() );
            request.setAttribute("customerList", CustomerDAO.getAllCustomerNamesNoStringsAttached());
            request.setAttribute("salesPersonList", NewCustomerDAO.getSalesPersonList(null));
            request.setAttribute( "usersList", ExternalUserSetupDAO.loadAllExternalUsers(false) );
            return mapping.findForward( "search" );

        }

        //when the action is for creating a new user
        clearForm( externalUserSetupForm );
        Calendar cal = Calendar.getInstance();
		cal.add(java.util.Calendar.MONTH,6);
		java.util.Date dt = cal.getTime();
        externalUserSetupForm.getExternalUser().setExpiresOn(StringUtils.formatDateToString(dt,"MM/dd/yyyy"));
        externalUserSetupForm.getExternalUser().setFunctionAccessList( ExternalUserSetupDAO.loadAllExternalFunctionalities( null ) );
        request.setAttribute( "vendorList", ExternalUserSetupDAO.getAllVendorNames() );
        request.setAttribute("customerList", CustomerDAO.getAllCustomerNamesNoStringsAttached());
        request.setAttribute("salesPersonList", NewCustomerDAO.getSalesPersonList(null));
        request.setAttribute( "usersList", ExternalUserSetupDAO.loadAllExternalUsers(false) );
        return mapping.findForward( "success" );
    }

    private HashMap validateForm( ExternalUserSetupForm eusf, String action )
    {

        HashMap errors = new LinkedHashMap();
        User externalUser = eusf.getExternalUser();

        if ( action.equalsIgnoreCase( "save" ) )
        {
            if ( ( externalUser.getUserId() == null ) || ( externalUser.getUserId().trim().length() == 0 ) )
            {
                errors.put( "User ID", "User ID required" );
            }
            if ( externalUser.getUserType() == Constants.USER_TYPE_VENDOR )
            {
                if ( externalUser.getVendorId() == -1  )
                {
                    errors.put( "Vendor", "Please select Vendor" );
                }
            }

        }

        if ( ( externalUser.getPassword() != null ) && ( externalUser.getPassword().equals( eusf.getReEnterPassword() ) == false ) )
        {
            errors.put( "Password", "Password did not match" );
        }

        if ( ( externalUser.getFirstName() != null ) && ( externalUser.getFirstName().trim().length() == 0 ) )
        {
            errors.put( "First Name", "First Name Required" );
        }

        if ( ( externalUser.getEmail() == null ) || ( externalUser.getEmail().trim().length() == 0 ) )
        {
            errors.put( "Email", "Email required" );
        }
        else if ( externalUser.getEmail().indexOf( "@" ) == -1 )
        {
            errors.put( "Email", "Invalid Email" );
        }

        return errors;
    }

    /**
     * This method resets all the properties to there default values
     *
     * @param externalUserSetupForm
     */
    private void clearForm( ExternalUserSetupForm externalUserSetupForm )
    {
        externalUserSetupForm.setExternalUserId( null );
        externalUserSetupForm.setPassword( null );
        externalUserSetupForm.setReEnterPassword( null );
        externalUserSetupForm.setFirstName( null );
        externalUserSetupForm.setLastName( null );
        externalUserSetupForm.setPhoneNumber( null );
        externalUserSetupForm.setFaxNumber( null );
        externalUserSetupForm.setEmail( null );
        externalUserSetupForm.setExpiresOn( null );
        externalUserSetupForm.setUserAction( null );
        externalUserSetupForm.setVendorId( -1 );
        externalUserSetupForm.setExternalUser( new User() );
    }

    /**
     * This method sets the function accesses to which the user5 has access to in the main list.
     *
     * @param totalList is the list of all the function accesses
     * @param userList  is the list of function accesses to which the user has access to
     */
    private void setSelectedFunctionAccess( ArrayList totalList, ArrayList userList )
    {
        FunctionAccess functionAccess = null;
        FunctionAccess userFunctionAccess = null;
        Iterator totalListIterator = totalList.iterator();
        Iterator userListIterator = null;

        while ( totalListIterator.hasNext() )
        {
            functionAccess = ( FunctionAccess ) totalListIterator.next();
            userListIterator = userList.iterator();

            while ( userListIterator.hasNext() )
            {
                userFunctionAccess = ( FunctionAccess ) userListIterator.next();
                functionAccess.setUserlId( userFunctionAccess.getUserId() );
                if ( functionAccess.getFunctionId() == userFunctionAccess.getFunctionId() )
                {
                    functionAccess.setFatId( userFunctionAccess.getFatId() );
                    functionAccess.setView( userFunctionAccess.getView() );
                    functionAccess.setModify( userFunctionAccess.getModify() );
                    functionAccess.setDelete( userFunctionAccess.getDelete() );
                    break;
                }
            }

        }

    }
}
